﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Collections;
using System.Reflection;
using CH.Easy.DbProvider.Common;
using CH.Easy.DbProvider.Interface;
using CH.Easy.DbProvider.Entity;
using CH.Easy.DbProvider.ExpressionExtend;

namespace CH.Easy.DbProvider.Core
{
    public class DbTable<TEntity> : IDbTable<TEntity>
    {

        public DbProviderType DbProviderType { get; set; }
        public DbTable(DbProviderType dbProviderType)
        {
            DbTableProvider dbTableProvider = (DbTableProvider)Assembly.GetExecutingAssembly().CreateInstance("CH.Easy.DbProvider.Provider." + dbProviderType.ToString() + "DbProvider");
            dbTableProvider.TableName = typeof(TEntity).Name;
            this.Provider = dbTableProvider;
            this.Expression = Expression.Constant(this);
        }
        public DbTable(IQueryProvider provider)
        {
            this.Provider = provider;
            this.Expression = Expression.Constant(this);
        }
        public DbTable(IQueryProvider provider, Expression expression)
        {
            this.Provider = provider;
            this.Expression = expression;
        }


        public IEnumerator<TEntity> GetEnumerator()
        {
            return (this.Provider.Execute<IEnumerable<TEntity>>(this.Expression)).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return (Provider.Execute<IEnumerable>(this.Expression)).GetEnumerator();
        }

        public Type ElementType
        {
            get { return typeof(TEntity); }
        }

        public override string ToString()
        {
            ExpressionSolution solution = new ExpressionSolution(this.DbProviderType);
            SolutionResult solutionResult = solution.Work(this.Expression);
            return solutionResult.CmdText;

        }




        public Expression Expression
        {
            get;
            private set;
        }

        public IQueryProvider Provider
        {
            get;
            private set;
        }








        public int Add(object obj)
        {
            this.Expression = new AddExpression(obj);
            int result = Provider.Execute<int>(this.Expression);
            if (result != 0)
            {
                AddExpression ie = this.Expression as AddExpression;
                if (ie.IsIdentity)
                {
                    ie.t.GetProperty(ie.PrimaryKey).SetValue(obj, result, null);
                }
            }

            return result;
        }
        public int Remove(Specification<TEntity> s)
        {
            this.Expression = new RemoveExpression(typeof(TEntity), s.Sp);
            return Provider.Execute<int>(this.Expression);
        }
        public int Remove(Expression<Func<TEntity, bool>> s)
        {
            this.Expression = new RemoveExpression(typeof(TEntity), s);
            return Provider.Execute<int>(this.Expression);
        }
        public int Modify(TEntity t, Specification<TEntity> s, params string[] modifyColumns)
        {
            this.Expression = new ModifyExpression(t, s.Sp, modifyColumns);
            return Provider.Execute<int>(this.Expression);
        }
        public int Modify(TEntity t, Expression<Func<TEntity, bool>> s, params string[] modifyColumns)
        {
            this.Expression = new ModifyExpression(t, s, modifyColumns);
            return Provider.Execute<int>(this.Expression);
        }






    }
}
